﻿#region Apache 2.0 License header

//   Copyright 2012 Lesley van Zijl
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. 

#endregion

using System.Reflection;
using System.Reflection.Emit;
using FavourObjects;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Tests.Helpers;

namespace Tests
{
    [TestClass]
    public class PropertyTests
    {
        #region Property tests with value types

        [TestMethod]
        public void Private_Property_GetSet_ValueType()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyValueType>(new TargetTestClass());

            favourObject.PropertyValueTypeGetSet = 17;
            Assert.AreEqual(17, favourObject.PropertyValueTypeGetSet);

            favourObject.PropertyValueTypeGetSet = default(int);
        }

        [TestMethod]
        public void Private_Property_Get_ValueType()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyValueType>(new TargetTestClass());

            Assert.AreEqual(5, favourObject.PropertyValueTypeGet);
        }

        [TestMethod]
        public void Private_Property_Set_ValueType()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyValueType>(new TargetTestClass());

            favourObject.PropertyValueTypeSet = 17;
        }


        [TestMethod]
        public void PrivateStatic_Property_ValueType_Get()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyValueType>(new TargetTestClass());

            Assert.AreEqual(29, favourObject.PropertyStaticValueTypeGet);
        }

        [TestMethod]
        public void PrivateStatic_Property_ValueType_Set()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyValueType>(new TargetTestClass());

            favourObject.PropertyStaticValueTypeGetSet = 69;
        }

        [TestMethod]
        public void PrivateStatic_Property_ValueType_GetSet()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyValueType>(new TargetTestClass());

            favourObject.PropertyStaticValueTypeGetSet = 69;

            Assert.AreEqual(69, favourObject.PropertyStaticValueTypeGetSet);
        }

        public interface IPrivatePropertyValueType
        {
            int PropertyValueTypeGetSet { get; set; }
            int PropertyValueTypeGet { get; }
            int PropertyValueTypeSet { set; }
            int PropertyStaticValueTypeGetSet { get; set; }
            int PropertyStaticValueTypeGet { get; }
            int PropertyStaticValueTypeSet { set; }
        }

        #endregion

        #region Property tests with reference types

        [TestMethod]
        public void Private_Property_GetSet_ReferenceType()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyReferenceType>(new TargetTestClass());

            favourObject.PropertyReferenceTypeGetSet = new DynamicMethod("F", typeof (double), null);

            MethodInfo testObject = favourObject.PropertyReferenceTypeGetSet;

            Assert.AreEqual(testObject.Name, "F");
            Assert.AreEqual(testObject.ReturnType, typeof (double));

            favourObject.PropertyReferenceTypeGetSet = null;
        }

        [TestMethod]
        public void Private_Property_Get_ReferenceType()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyReferenceType>(new TargetTestClass());

            MethodInfo testObject = favourObject.PropertyReferenceTypeGet;

            Assert.AreEqual(testObject.Name, "F");
            Assert.AreEqual(testObject.ReturnType, typeof (int));
        }

        [TestMethod]
        public void Private_Property_Set_ReferenceType()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyReferenceType>(new TargetTestClass());

            favourObject.PropertyReferenceTypeSet = new DynamicMethod("F", typeof (byte), null);
        }


        [TestMethod]
        public void PrivateStatic_Property_ReferenceType_Get()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyReferenceType>(new TargetTestClass());

            MethodInfo testObject = favourObject.PropertyStaticReferenceTypeGet;

            Assert.AreEqual("F", testObject.Name);
            Assert.AreEqual(typeof (double), testObject.ReturnType);
        }

        [TestMethod]
        public void PrivateStatic_Property_ReferenceType_Set()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyReferenceType>(new TargetTestClass());

            favourObject.PropertyStaticReferenceTypeGetSet = new DynamicMethod("F", typeof (double), null);
        }

        [TestMethod]
        public void PrivateStatic_Property_ReferenceType_GetSet()
        {
            var favourObject = FavourObject.Create<IPrivatePropertyReferenceType>(new TargetTestClass());

            favourObject.PropertyStaticReferenceTypeGetSet = new DynamicMethod("F", typeof (double), null);

            MethodInfo testObject = favourObject.PropertyStaticReferenceTypeGetSet;

            Assert.AreEqual(testObject.Name, "F");
            Assert.AreEqual(testObject.ReturnType, typeof (double));
        }

        public interface IPrivatePropertyReferenceType
        {
            MethodInfo PropertyReferenceTypeGetSet { get; set; }
            MethodInfo PropertyReferenceTypeGet { get; }
            MethodInfo PropertyReferenceTypeSet { set; }
            MethodInfo PropertyStaticReferenceTypeGetSet { get; set; }
            MethodInfo PropertyStaticReferenceTypeGet { get; }
            MethodInfo PropertyStaticReferenceTypeSet { set; }
        }

        #endregion
    }
}